]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
Add check_cloexec_fds debug command
authorDaniel Drake <drake@endlessm.com>
Fri, 27 Jul 2018 16:30:22 +0000 (11:30 -0500)
committerFlorian Müllner <florian.muellner@gmail.com>
Mon, 30 Jul 2018 23:11:41 +0000 (23:11 +0000)
Add a debug command (to be executed manually via Alt+F2) to check
that all of gnome-shell's file descriptors have the CLOEXEC flag set.
This is important so that internal file descriptors do not get passed
to apps when they are launched.

It prints a warning message for every fd that does not have the flag set.

fdwalk() is used from the standard library if available (it is not
available in glibc), otherwise we use the same implementation as glib
has internally.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/132

config.h.meson
js/ui/runDialog.js
meson.build
src/shell-util.c
src/shell-util.h

index 0dac17b9478a7768c3886e819a75348342d27676..141b2240a82f69d822de08349f587d2c85e9a4f9 100644 (file)
@@ -27,3 +27,6 @@
 
 /* Define if you have the `g_desktop_app_info_launch_uris_as_manager_with_fds` function */
 #mesondefine HAVE_GIO_DESKTOP_LAUNCH_URIS_WITH_FDS
+
+/* Define if fdwalk is available in libc */
+#mesondefine HAVE_FDWALK
index 606a683962c39d1adabb99f7f92fae5c9e8b4ffe..b514f5b9f0d8156f7a154a1b7a71d1a3cb98fe0c 100644 (file)
@@ -62,7 +62,11 @@ var RunDialog = new Lang.Class({
                                    'rt': () => {
                                        Main.reloadThemeResource();
                                        Main.loadTheme();
-                                   }
+                                   },
+
+                                   'check_cloexec_fds': () => {
+                                       Shell.util_check_cloexec_fds();
+                                   },
                                  };
 
 
index 5750b4fecd3239e03b0b7a91bf91ca53156cf9c6..cafba27a82538b0c9320ab3f39388e63d610e397 100644 (file)
@@ -173,6 +173,10 @@ cdata.set('HAVE__NL_TIME_FIRST_WEEKDAY',
   cc.has_header_symbol('langinfo.h', '_NL_TIME_FIRST_WEEKDAY')
 )
 
+cdata.set('HAVE_FDWALK',
+          cc.has_function('fdwalk')
+)
+
 config_h = configure_file(
   input: 'config.h.meson',
   output: 'config.h',
index 70b8c06110ba1fe5764f75c40aee099c2b2684a5..411f5fad724a9d15efed8cd29883109d2ea54cf9 100644 (file)
@@ -2,8 +2,15 @@
 
 #include "config.h"
 
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
 #include <sys/types.h>
 #include <sys/wait.h>
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
 
 #include <GL/gl.h>
 #include <cogl/cogl.h>
@@ -514,3 +521,104 @@ shell_util_composite_capture_images (ClutterCapture  *captures,
 
   return image;
 }
+
+#ifndef HAVE_FDWALK
+static int
+fdwalk (int (*cb)(void *data, int fd), void *data)
+{
+  gint open_max;
+  gint fd;
+  gint res = 0;
+
+#ifdef HAVE_SYS_RESOURCE_H
+  struct rlimit rl;
+#endif
+
+#ifdef __linux__
+  DIR *d;
+
+  if ((d = opendir("/proc/self/fd"))) {
+      struct dirent *de;
+
+      while ((de = readdir(d))) {
+          glong l;
+          gchar *e = NULL;
+
+          if (de->d_name[0] == '.')
+              continue;
+
+          errno = 0;
+          l = strtol(de->d_name, &e, 10);
+          if (errno != 0 || !e || *e)
+              continue;
+
+          fd = (gint) l;
+
+          if ((glong) fd != l)
+              continue;
+
+          if (fd == dirfd(d))
+              continue;
+
+          if ((res = cb (data, fd)) != 0)
+              break;
+        }
+
+      closedir(d);
+      return res;
+  }
+
+  /* If /proc is not mounted or not accessible we fall back to the old
+   * rlimit trick */
+
+#endif
+
+#ifdef HAVE_SYS_RESOURCE_H
+  if (getrlimit(RLIMIT_NOFILE, &rl) == 0 && rl.rlim_max != RLIM_INFINITY)
+      open_max = rl.rlim_max;
+  else
+#endif
+      open_max = sysconf (_SC_OPEN_MAX);
+
+  for (fd = 0; fd < open_max; fd++)
+      if ((res = cb (data, fd)) != 0)
+          break;
+
+  return res;
+}
+#endif
+
+static int
+check_cloexec(void *data, gint fd)
+{
+  int r;
+
+  if (fd < 3)
+    return 0;
+
+  r = fcntl (fd, F_GETFD);
+  if (r < 0)
+    return 0;
+
+  if (!(r & FD_CLOEXEC))
+    g_warning ("fd %d is not CLOEXEC", fd);
+
+  return 0;
+}
+
+/**
+ * shell_util_check_cloexec_fds:
+ *
+ * Walk over all open file descriptors. Check them for the FD_CLOEXEC flag.
+ * If this flag is not set, log the offending file descriptor number.
+ *
+ * It is important that gnome-shell's file descriptors are all marked CLOEXEC,
+ * so that the shell's open file descriptors are not passed to child processes
+ * that we launch.
+ */
+void
+shell_util_check_cloexec_fds (void)
+{
+  fdwalk (check_cloexec, NULL);
+  g_info ("Open fd CLOEXEC check complete");
+}
index 2218594c19ed2c5c624bc5941417675b2f2bc7ec..408b55f68d1f817fdb4864ac78a034c58b891e48 100644 (file)
@@ -60,6 +60,8 @@ cairo_surface_t * shell_util_composite_capture_images (ClutterCapture  *captures
                                                        int              width,
                                                        int              height);
 
+void shell_util_check_cloexec_fds (void);
+
 G_END_DECLS
 
 #endif /* __SHELL_UTIL_H__ */